package backtest

import (
	"math"
	"sort"

	"nofx/market"
)

// ResampleEquity 根据时间周期重采样资金曲线。
func ResampleEquity(points []EquityPoint, timeframe string) ([]EquityPoint, error) {
	if timeframe == "" {
		return points, nil
	}
	dur, err := market.TFDuration(timeframe)
	if err != nil {
		return nil, err
	}
	if len(points) == 0 {
		return points, nil
	}

	durMs := dur.Milliseconds()
	if durMs <= 0 {
		return points, nil
	}

	bucketMap := make(map[int64]EquityPoint)
	bucketKeys := make([]int64, 0)
	for _, pt := range points {
		bucket := (pt.Timestamp / durMs) * durMs
		if _, exists := bucketMap[bucket]; !exists {
			bucketKeys = append(bucketKeys, bucket)
		}
		bucketPoint := pt
		bucketPoint.Timestamp = bucket
		bucketMap[bucket] = bucketPoint
	}

	sort.Slice(bucketKeys, func(i, j int) bool {
		return bucketKeys[i] < bucketKeys[j]
	})

	resampled := make([]EquityPoint, 0, len(bucketKeys))
	for _, key := range bucketKeys {
		resampled = append(resampled, bucketMap[key])
	}

	return resampled, nil
}

// LimitEquityPoints 将数据点数量限制在给定范围内（均匀抽样）。
func LimitEquityPoints(points []EquityPoint, limit int) []EquityPoint {
	if limit <= 0 || len(points) <= limit {
		return points
	}

	step := float64(len(points)) / float64(limit)
	result := make([]EquityPoint, 0, limit)
	for i := 0; i < limit; i++ {
		idx := int(math.Round(step * float64(i)))
		if idx >= len(points) {
			idx = len(points) - 1
		}
		result = append(result, points[idx])
	}

	return result
}

// LimitTradeEvents 同样对交易事件按均匀抽样。
func LimitTradeEvents(events []TradeEvent, limit int) []TradeEvent {
	if limit <= 0 || len(events) <= limit {
		return events
	}

	step := float64(len(events)) / float64(limit)
	result := make([]TradeEvent, 0, limit)
	for i := 0; i < limit; i++ {
		idx := int(math.Round(step * float64(i)))
		if idx >= len(events) {
			idx = len(events) - 1
		}
		result = append(result, events[idx])
	}
	return result
}

// AlignEquityTimestamps 确保时间戳按升序排列。
func AlignEquityTimestamps(points []EquityPoint) []EquityPoint {
	sort.Slice(points, func(i, j int) bool {
		return points[i].Timestamp < points[j].Timestamp
	})
	return points
}
